#include <sys/time.h>
#include <boost/thread/mutex.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "LogStream.h"

#define now to_simple_string( microsec_clock::local_time() )

using namespace boost::posix_time;
using namespace boost::gregorian;
using namespace kc_sf;

// ------------------------------------------------------------------ //

// @param append	czy dopisywać do pliku, czy nadpisać jego zawartość
LogStream::LogStream( const std::string &log_filename, bool append )
: ls_filename( log_filename )
{
	boost::mutex::scoped_lock lock( ls_guard );
	
	if (!this->open (append) )
	{
		std::cerr << "Uwaga! Plik logów: " << log_filename
			<< " - brak dostępu" << std::endl;
	}
	else
		ls_stream << now << "\t" << "Otwarto plik dziennika zdarzeń" << std::endl;
}

// ------------------------------------------------------------------ //

LogStream::~LogStream()
{
	close();
}

// ------------------------------------------------------------------ //

// @param append	czy dopisywać do pliku, czy nadpisać jego zawartość
LogStream & 
LogStream::getInstance( const std::string &log_filename, bool append )
{
	static LogStream ls_instance (log_filename, append);  // stworzenie instancji klasy - Meyers singleton -> sam sie umie zamknąć
	return ls_instance;
}

// ------------------------------------------------------------------ //

// znaczek_czasu wiadomość
bool LogStream::write( const std::string &log_message )
{
	bool success = false;
	
	if (this->isOpened() )
	{
		boost::mutex::scoped_lock lock( ls_guard );
		ls_stream << now << "\t" << log_message << std::endl;
		success = true;
	}

	return success;
}

// ------------------------------------------------------------------ //

// znaczek_czasu priorytet wiadomość
bool LogStream::write( const std::string &priority_name, 
					   const std::string &log_message )
{
	bool success = false;
	
	if (this->isOpened() )
	{	
		boost::mutex::scoped_lock lock( ls_guard );
		ls_stream << now << "\t" << priority_name << " " << log_message << std::endl;
		success = true;
	}

	return success;
}

// ------------------------------------------------------------------ //

// manipulator sposobu zapisu
bool LogStream::write( OStreamManipPtr manip )
{
	bool success = false;
	
	if (this->isOpened() )
	{	
		boost::mutex::scoped_lock lock( ls_guard );
		manip( ls_stream );				// zmiana stanu strumienia
		success = true;
	}

	return success;
}

// ------------------------------------------------------------------ //

// próbuje otworzyc plik logu
bool LogStream::open (bool append)
{
	bool success = true;

	if( !ls_stream.is_open() )
	{
		if( append )
			ls_stream.open( ls_filename.c_str(), 
							std::ios_base::app | std::ios_base::ate );  // dopisuj do pliku
		else
			ls_stream.open( ls_filename.c_str(), 
							std::ios_base::out );  // nadpisz plik
		
		success = ls_stream.is_open() ? true : false;
	}

	return success;
}

// ------------------------------------------------------------------ //

bool LogStream::isOpened()
{
	boost::mutex::scoped_lock lock( ls_guard );
	return ls_stream.is_open();
}

// ------------------------------------------------------------------ //

void LogStream::close()
{	
	if (this->isOpened() )
	{
		boost::mutex::scoped_lock lock( ls_guard );
		ls_stream << now << "\t" << "Zamknięto plik dziennika zdarzeń" << std::endl;
		ls_stream.close();
	}
}
